﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace PMC.Plugins
{
    public abstract class StatePlugin : PluginBase
    {
        protected Wbrowser Context;

        public StatePlugin(Wbrowser webbrowser)
        {
            Context = webbrowser;
        }

        public virtual void OnEntry()
        {
        }

        /// <summary>
        /// Virtual DoAction
        /// </summary>
        public virtual void DoAction()
        {
        }

        public virtual void OnExit()
        {
        }

        //Need thoughts
        protected void NavigateNext()
        {
            Context.Next();
        }

        #region Protected Methods
        /// <summary>
        /// Find the first element that has an attribute with the given equals
        /// </summary>
        /// <param name="tagname">HTML Tagname</param>
        /// <param name="attribute">Attribute that the element must contain</param>
        /// <param name="equals">The value that the attribute should hold</param>
        /// <param name="ignorecase">Wether the value of the attribute (equals) should be case-sensitive</param>
        /// <returns>Returns the matching HtmlElement and if none found; null</returns>
        protected HtmlElement FindElement(string tagname, string attribute, string equals, bool ignorecase)
        {
            string[] attributes = new string[] { attribute };
            string[] _equals = new string[] { equals };
            return FindElement(tagname, attributes, _equals, ignorecase);
        }

        /// <summary>
        /// Find the first element that has the attributes with the given equals
        /// </summary>
        /// <param name="tagname">HTML Tagname</param>
        /// <param name="attribute">Attributes that the element must contain</param>
        /// <param name="equals">The values that the attributes should hold</param>
        /// <param name="ignorecase">Wether the value of the attribute (equals) should be case-sensitive</param>
        /// <returns>Returns the matching HtmlElement and if none found; null</returns>
        protected HtmlElement FindElement(string tagname, string[] attributes, string[] equals, bool ignorecase)
        {
            //If the amount of attributes is of different size than equals
            if (attributes.Length != equals.Length)
                throw new ArgumentException("Attributes and equals do not have the same length");

            //If case is insensitive, make the array in lower case
            if (ignorecase)
            {
                for (int i = 0; i < attributes.Length; i++)
                {
                    attributes[i] = attributes[i].ToLower();
                    equals[i] = equals[i].ToLower();
                }
            }

            //enumerate through the collection with the given tagname
            foreach (HtmlElement el in GetCollection(tagname))
            {
                bool isSame = true; //At this point, all the attributes have the expected value given in equals
                for (int i = 0; i < attributes.Length; i++)
                {
                    string attribute = (!ignorecase) ? el.GetAttribute(attributes[i]) : el.GetAttribute(attributes[i]).ToLower();
                    if (!attribute.Equals(equals[i]))
                    {
                        isSame = false; //A different value has been found, which not matches the equals
                        break; //break out of the loop
                    }
                }
                if (isSame)
                    return el; //All the attributes matched the given equals and HtmlElement is returned
            }
            return null; //No HtmlElement did match the expectations, null is returned
        }

        /// <summary>
        /// Gets a HTMLElementCollection with HtmlElements matching the given tagname (in JS: getElementsByTagName)
        /// </summary>
        /// <param name="Tagname">Html tagname</param>
        /// <returns>HtmlElementCollection</returns>
        protected HtmlElementCollection GetCollection(string Tagname)
        {
            return Context.Document.GetElementsByTagName(Tagname);
        }

        /// <summary>
        /// Get a single element with the given ID (in JS: getElementById)
        /// </summary>
        /// <param name="id">Id of the given element</param>
        /// <returns>HtmlElement with the id or else null</returns>
        protected HtmlElement GetElement(string id)
        {
            return Context.Document.GetElementById(id);
        }
        #endregion
    }
}